package at.codebase.web.servlets.item;

import static at.codebase.web.util.i18n.I18NFactory.i18n;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;

import at.codebase.core.log.Log;
import at.codebase.db.dao.EItemDao;
import at.codebase.db.entities.EItem;
import at.codebase.db.entities.EUser;
import at.codebase.security.SecureStringBuilder;
import at.codebase.web.servlets.item.ItemInputStatus.*;
import at.codebase.web.templates.ErrorWidget;
import at.codebase.web.templates.MainTemplate;
import at.codebase.web.util.LocalRequest.RequestInformation;
import at.codebase.web.util.URLParameters.ParameterException;
import at.codebase.web.util.api.ApiPartnerCalls;
import at.codebase.web.util.servlet.SecureServlet;
import at.codebase.web.util.template.Template;
import at.codebase.web.util.template.TemplateEngine;

/**
 * Used to create new items.
 * 
 * @author Lukas Pfeifhofer <lukas.pfeifhofer@devlabs.pro>
 */
@SuppressWarnings("rawtypes")
public class ItemAdd extends SecureServlet {

	static HashMap<String, InputStatus> emptyInputStatusMap = new HashMap<String, InputStatus>();

	static {
		emptyInputStatusMap.put("itemTitle", new InputStatusVoid());
		emptyInputStatusMap.put("itemPrice", new InputStatusVoid());
		emptyInputStatusMap.put("itemDescription", new InputStatusVoid());
		emptyInputStatusMap.put("itemExpirationDate", new InputStatusVoid(
				"week2"));
		emptyInputStatusMap.put("latitude", new InputStatusVoid());
		emptyInputStatusMap.put("longitude", new InputStatusVoid());
	}

	@Override
	protected RequestType requestType() {
		return RequestType.POST_AND_GET;
	}

	@Override
	protected void initSecurityLevels(ArrayList<UserLevel> secLevels) {
		secLevels.add(UserLevel.REGISTERED);
		secLevels.add(UserLevel.ADMIN);
	}

	@Override
	protected void processRequestSecurityLevel(RequestInformation requestInfo,
			UserLevel level, RequestType requestType) {
		if (requestType.equals(RequestType.POST)) {
			if(!tokenCorrect(requestInfo)) {
				processRequestNoAccess(requestInfo, level);
				return;
			}
			
			HashMap<String, InputStatus> inputStatusMap = new HashMap<String, InputStatus>();

			try {
				inputStatusMap.put("itemTitle", new InputStatusTitle(
						requestInfo.getParameters().getString("itemTitle")));
			} catch (ParameterException e) {
				inputStatusMap.put("itemTitle", new InputStatusTitle(null));
			}

			try {
				inputStatusMap.put("itemPrice", new InputStatusPrice(
						requestInfo.getParameters().getString("itemPrice")));
			} catch (ParameterException e) {
				inputStatusMap.put("itemPrice", new InputStatusPrice(null));
			}

			try {
				inputStatusMap.put("itemDescription",
						new InputStatusDescription(requestInfo.getParameters()
								.getString("itemDescription")));
			} catch (ParameterException e) {
				inputStatusMap.put("itemDescription",
						new InputStatusDescription(null));
			}

			try {
				inputStatusMap.put("itemExpirationDate",
						new InputStatusExpirationDate(requestInfo
								.getParameters()
								.getString("itemExpirationDate")));
			} catch (ParameterException e) {
				inputStatusMap.put("itemExpirationDate",
						new InputStatusExpirationDate(null));
			}

			if (requestInfo.getParameters().isExisting("useLocation")) {
				try {
					inputStatusMap.put("latitude", new InputStatusLatitude(
							requestInfo.getParameters().getString("latitude")));
				} catch (ParameterException e) {
					inputStatusMap.put("latitude",
							new InputStatusLatitude(null));
				}

				try {
					inputStatusMap
							.put("longitude",
									new InputStatusLongitude(requestInfo
											.getParameters().getString(
													"longitude")));
				} catch (ParameterException e) {
					inputStatusMap.put("longitude", new InputStatusLongitude(
							null));
				}
			}

			boolean allValid = true;

			for (String key : inputStatusMap.keySet()) {
				InputStatus inputStatus = inputStatusMap.get(key);
				inputStatus.compile();
				if (inputStatus.isError())
					allValid = false;
			}

			if (allValid) {
				// Everyone is happy - add Items and go on...
				String itemTitle = ((InputStatusTitle) inputStatusMap
						.get("itemTitle")).getValue();
				String itemDescription = ((InputStatusDescription) inputStatusMap
						.get("itemDescription")).getValue();
				double itemPrice = ((InputStatusPrice) inputStatusMap
						.get("itemPrice")).getValue().doubleValue();
				int expirationOffset = ((InputStatusExpirationDate) inputStatusMap
						.get("itemExpirationDate")).getValue().intValue();

				long timeCreate = System.currentTimeMillis();
				long timeExpiration = timeCreate + (expirationOffset * 1000);

				boolean useLocation = requestInfo.getParameters().isExisting(
						"useLocation");

				EItem item;
				if (useLocation) {
					double latitude = ((InputStatusLatitude) inputStatusMap
							.get("latitude")).getValue().doubleValue();
					double longitude = ((InputStatusLongitude) inputStatusMap
							.get("longitude")).getValue().doubleValue();
					item = EItem.createItem(
							EUser.ref(requestInfo.getUser().getId(), requestInfo.getUser()),
							itemTitle, itemDescription, itemPrice, timeCreate,
							timeExpiration, latitude, longitude);
				} else {
					item = EItem.createItem(
							EUser.ref(requestInfo.getUser().getId(), requestInfo.getUser()),
							itemTitle, itemDescription, itemPrice, timeCreate,
							timeExpiration);
				}
				EItemDao.addItem(item);
				Log.logItem(requestInfo.getUser().getId(), "User (userid="
						+ requestInfo.getUser().getId()
						+ ") created item (itemid=" + item.getId() + ")");

				ApiPartnerCalls.notifyAboutNewItem(item, requestInfo.getHostUrl());
				
				redirectTo("/item/" + item.getId().toString());

			} else {
				buildPage(requestInfo, inputStatusMap);
			}
		} else {
			buildPage(requestInfo, emptyInputStatusMap);
		}
	}

	private void buildPage(RequestInformation requestInfo,
			HashMap<String, InputStatus> inputStatusMap) {
		MainTemplate mainTemplate = new MainTemplate(requestInfo, writer());
		mainTemplate.setTitle(i18n(requestInfo.getLocale()).string(
				"itemAdd_title"));
		mainTemplate.addJSScript("script_item_add.js");

		// ErrorWidget
		ErrorWidget errorWidget = new ErrorWidget();
		if (inputStatusMap.get("itemTitle").isError())
			errorWidget.addErrorItem(i18n(requestInfo.getLocale()).string(
					"itemAdd_titleError"));
		if (inputStatusMap.get("itemPrice").isError())
			errorWidget.addErrorItem(i18n(requestInfo.getLocale()).string(
					"itemAdd_priceError"));
		if (inputStatusMap.get("itemDescription").isError())
			errorWidget.addErrorItem(i18n(requestInfo.getLocale()).string(
					"itemAdd_descriptionError"));
		if (inputStatusMap.get("itemExpirationDate").isError())
			errorWidget.addErrorItem(i18n(requestInfo.getLocale()).string(
					"itemAdd_expirationDateError"));
		if (requestInfo.getParameters().isExisting("useLocation")) {
			if (inputStatusMap.get("latitude").isError())
				errorWidget.addErrorItem(i18n(requestInfo.getLocale()).string(
						"itemAdd_locationError"));
			else if (inputStatusMap.get("longitude").isError())
				errorWidget.addErrorItem(i18n(requestInfo.getLocale()).string(
						"itemAdd_locationError"));
		}

		Template newItemTemplate = TemplateEngine
				.getTemplate("item/site_add_item.html");
		
		newItemTemplate.setText("randomKey", nextToken());

		if (errorWidget.hasErrors())
			newItemTemplate.setTemplate("errorWidget", errorWidget);

		newItemTemplate.setHTML("itemTitleValue", new SecureStringBuilder()
				.appendSecure(inputStatusMap.get("itemTitle").getRawString())
				.toString());
		newItemTemplate.setHTML("itemPriceValue", new SecureStringBuilder()
				.appendSecure(inputStatusMap.get("itemPrice").getRawString())
				.toString());
		newItemTemplate.setHTML(
				"itemDescriptionValue",
				new SecureStringBuilder().appendSecure(
						inputStatusMap.get("itemDescription").getRawString())
						.toString());
		newItemTemplate.setText(
				"itemAdd_useLocation",
				new SecureStringBuilder().appendSecure(
						i18n(requestInfo.getLocale()).string(
								"itemAdd_useLocation")).toString());

		// Expiration Date Dropdown List
		HashMap<String, Integer> timePeriods = InputStatusExpirationDate.timePeriods;
		String[] keys = Arrays.copyOf(timePeriods.keySet().toArray(),
				timePeriods.keySet().toArray().length, String[].class);
		Arrays.sort(keys);

		SecureStringBuilder dropdownBuffer = new SecureStringBuilder();
		for (String key : keys) {
			dropdownBuffer.appendInsecure("<option value=\"");
			dropdownBuffer.appendSecure(key);
			dropdownBuffer.appendInsecure("\" ");
			if (key.equals(inputStatusMap.get("itemExpirationDate")
					.getRawString()))
				dropdownBuffer.appendInsecure("selected=\"selected\"");
			dropdownBuffer.appendInsecure(">");
			dropdownBuffer.appendSecure(i18n(requestInfo.getLocale()).string(
					"itemAdd_expirationDate_" + key));
			dropdownBuffer.appendInsecure("</option>");
		}
		newItemTemplate.setHTML("itemExpirationDateOptions",
				dropdownBuffer.toString());

		Template googleMapTemplate = TemplateEngine
				.getTemplate("util/google_map_selection.html");
		googleMapTemplate.setText(
				"script_itemAdd_noSearchResults",
				i18n(requestInfo.getLocale()).string(
						"script_itemAdd_noSearchResults"));
		googleMapTemplate.setText("zoom", String.valueOf(0));
		if (requestInfo.getParameters().isExisting("useLocation")) {
			if (!inputStatusMap.get("latitude").getRawString().isEmpty()
					&& !inputStatusMap.get("longitude").getRawString()
							.isEmpty()) {
				googleMapTemplate.setText("latitude",
						inputStatusMap.get("latitude").getRawString());
				googleMapTemplate.setText("longitude",
						inputStatusMap.get("longitude").getRawString());
				googleMapTemplate.setText("hasInitLocation", "1");
			} else {
				googleMapTemplate.setText("latitude", "0.0");
				googleMapTemplate.setText("longitude", "0.0");
				googleMapTemplate.setText("hasInitLocation", "0");
			}
			newItemTemplate.setText("useLocationChecked", "checked");
		} else {
			googleMapTemplate.setText("hasInitLocation", "0");
			googleMapTemplate.setText("latitude", "0.0");
			googleMapTemplate.setText("longitude", "0.0");
			newItemTemplate.setText("useLocationChecked", "");
		}
		googleMapTemplate.setText("isFixed", "0");
		newItemTemplate.setTemplate("googleMapSelection", googleMapTemplate);

		mainTemplate.setTemplate("body", newItemTemplate);
		mainTemplate.render(requestInfo.getLocale());
	}

}
